package com.skyline.common.validation;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.validator.Arg;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.commons.validator.ValidatorException;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.support.DefaultMessageSourceResolvable;

import com.skyline.common.util.SpringUtils;

/**
 * 校验工具类
 * 
 * @author wuqh
 * */
public class ValidationUtils {
	private static final Log LOGGER = LogFactory.getLog(ValidationUtils.class);
	private static ValidationFactory factory = (ValidationFactory) SpringUtils.getBean(ValidationFactory.class);

	/**
	 * 判断是否有配置指定校验规则
	 * 
	 * @param formName
	 *            校验规则名
	 * */
	public static boolean hasRulesForForm(String formName) {
		return factory.hasRulesForBean(formName);
	}

	/**
	 * 校验数据，返回验证结果，把错误信息放到Errors中
	 * 
	 * @param formName
	 *            校验规则名
	 * @param dataBean
	 *            校验数据
	 * */
	public static <T> Errors validateForm(String formName, T dataBean) {
		Errors errors = new Errors();
		Validator validator = factory.getValidator(formName, dataBean, errors);
		try {
			validator.validate();
		} catch (ValidatorException e) {
			LOGGER.info("校验数据发生异常，校验的FormName为" + formName, e);
			errors.addError("SYSERROR", "系统发生异常，请重新尝试！");
		}
		return errors;
	}

	/**
	 * 判断验证是否通过
	 * @param errors 返回的验证结果
	 * */
	public static boolean isDataValide(Errors errors) {
		return !errors.hasErrors();
	}

	/**
	 * 获取结果中的所有错误信息
	 * @param errors 返回的验证结果
	 * */
	public static String[] getAllErrorMessages(Errors errors) {
		return errors.getErrors();
	}

	/**
	 * 获取结果中指定字段的错误信息
	 * @param errors 返回的验证结果
	 * @param fieldName 错误字段
	 * */
	public static String getErrorMessageOfField(Errors errors, String fieldName) {
		String errMsg = errors.getError(fieldName);
		if(StringUtils.isEmpty(errMsg)) {
			return null;
		} else {
			return errMsg;
		}
	}

	/**
	 * 拼接验证的所有错误信息
	 * @param errors 返回的验证结果
	 * @param separator 错误信息之间的分割符
	 * */
	public static String getMergedErrors(Errors errors, String separator) {
		StringBuilder msgs = new StringBuilder();
		String[] errMsgs = getAllErrorMessages(errors);
		for (String errMsg : errMsgs) {
			msgs.append(errMsg).append(separator);
		}
		return msgs.toString();
	}

	/**
	 * 获取配置文件msg的key
	 * */
	protected static String getMessageKey(ValidatorAction va, Field field) {
		return (field.getMsg(va.getName()) != null ? field.getMsg(va.getName()) : va.getMsg());
	}

	/**
	 * 获取配置文件msg的arg
	 * */
	protected static Object[] getArgs(ValidatorAction va, Field field) {

		List<Object> args = new ArrayList<Object>();
		String actionName = va.getName();

		if (field.getArg(actionName, 0) != null) {
			args.add(0, getMessage(field.getArg(actionName, 0)));
		}

		if (field.getArg(actionName, 1) != null) {
			args.add(1, getMessage(field.getArg(actionName, 1)));
		}

		if (field.getArg(actionName, 2) != null) {
			args.add(2, getMessage(field.getArg(actionName, 2)));
		}

		if (field.getArg(actionName, 3) != null) {
			args.add(3, getMessage(field.getArg(actionName, 3)));
		}

		return args.toArray();
	}

	/**
	 * 获取arg对应的文字
	 * */
	protected static Object getMessage(Arg arg) {
		if (arg.isResource()) {
			return createMessage(arg.getKey());
		} else {
			return arg.getKey();
		}
	}

	protected static MessageSourceResolvable createMessage(Object obj) {
		String[] codes = new String[] { String.valueOf(obj) };
		String defaultMsg = codes[0];
		return new DefaultMessageSourceResolvable(codes, null, defaultMsg);
	}

	static String getMessage(MessageSource messages, Locale locale, ValidatorAction va, Field field) {
		String code = getMessageKey(va, field);
		Object[] args = getArgs(va, field);
		return messages.getMessage(code, args, code, locale);//从spring中获取properties文件值的方法
	}

	static String getMessage(ValidatorAction va, Field field) {
		return getMessage(SpringUtils.getApplicationContext(), Locale.getDefault(), va, field);
	}
}
